home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / Mesa-2.2 / src-glu / nurbscrv.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-27  |  12.4 KB  |  481 lines

  1. /* $Id: nurbscrv.c,v 1.2 1996/09/27 23:12:22 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.0
  6.  * Copyright (C) 1995-1996  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: nurbscrv.c,v $
  26.  * Revision 1.2  1996/09/27 23:12:22  brianp
  27.  * added return 0 to get_surface_dim() to silence warning
  28.  *
  29.  * Revision 1.1  1996/09/27 01:19:39  brianp
  30.  * Initial revision
  31.  *
  32.  */
  33.  
  34.  
  35. /*
  36.  * NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
  37.  * See README2 for more info.
  38.  */
  39.  
  40.  
  41. #include <math.h>
  42. #include <stdlib.h>
  43. #include "nurbs.h"
  44.  
  45.  
  46. static int
  47. get_curve_dim(GLenum type)
  48. {
  49.     switch(type)
  50.     {
  51.         case GL_MAP1_VERTEX_3:            return 3;
  52.         case GL_MAP1_VERTEX_4:            return 4;
  53.         case GL_MAP1_INDEX:                return 1;
  54.         case GL_MAP1_COLOR_4:            return 4;
  55.         case GL_MAP1_NORMAL:            return 3;
  56.         case GL_MAP1_TEXTURE_COORD_1:    return 1;
  57.         case GL_MAP1_TEXTURE_COORD_2:    return 2;
  58.         case GL_MAP1_TEXTURE_COORD_3:    return 3;
  59.         case GL_MAP1_TEXTURE_COORD_4:    return 4;
  60.                 default:  abort();  /* TODO: is this OK? */
  61.     }
  62.         return 0; /*never get here*/
  63. }
  64.  
  65. static GLenum
  66. test_nurbs_curve(GLUnurbsObj *nobj, curve_attribs *attribs)
  67. {
  68.     GLenum err;
  69.     GLint tmp_int;
  70.  
  71.     if(attribs->order < 0)
  72.     {
  73.         call_user_error(nobj,GLU_INVALID_VALUE);
  74.         return GLU_ERROR;
  75.     }
  76.     glGetIntegerv(GL_MAX_EVAL_ORDER,&tmp_int);
  77.     if(attribs->order > tmp_int || attribs->order < 2)
  78.     {
  79.         call_user_error(nobj,GLU_NURBS_ERROR1);
  80.         return GLU_ERROR;
  81.     }
  82.     if(attribs->knot_count < attribs->order +2)
  83.     {
  84.         call_user_error(nobj,GLU_NURBS_ERROR2);
  85.         return GLU_ERROR;
  86.     }
  87.     if(attribs->stride < 0)
  88.     {
  89.         call_user_error(nobj,GLU_NURBS_ERROR34);
  90.         return GLU_ERROR;
  91.     }
  92.     if(attribs->knot==NULL || attribs->ctrlarray==NULL)
  93.     {
  94.         call_user_error(nobj,GLU_NURBS_ERROR36);
  95.         return GLU_ERROR;
  96.     }
  97.     if((err=test_knot(attribs->knot_count,attribs->knot,attribs->order))
  98.         !=GLU_NO_ERROR)
  99.     {
  100.         call_user_error(nobj,err);
  101.         return GLU_ERROR;
  102.     }
  103.     return GLU_NO_ERROR;
  104. }
  105.  
  106. static GLenum
  107. test_nurbs_curves(GLUnurbsObj *nobj)
  108. {
  109.     /* test the geometric data */
  110.     if(test_nurbs_curve(nobj,&(nobj->curve.geom))!=GLU_NO_ERROR)
  111.         return GLU_ERROR;
  112.     /* now test the attributive data */
  113.     /* color */
  114.     if(nobj->curve.color.type!=GLU_INVALID_ENUM)
  115.         if(test_nurbs_curve(nobj,&(nobj->curve.color))!=GLU_NO_ERROR)
  116.             return GLU_ERROR;
  117.     /* normal */
  118.     if(nobj->curve.normal.type!=GLU_INVALID_ENUM)
  119.         if(test_nurbs_curve(nobj,&(nobj->curve.normal))!=GLU_NO_ERROR)
  120.             return GLU_ERROR;
  121.     /* texture */
  122.     if(nobj->curve.texture.type!=GLU_INVALID_ENUM)
  123.         if(test_nurbs_curve(nobj,&(nobj->curve.texture))!=GLU_NO_ERROR)
  124.             return GLU_ERROR;
  125.     return GLU_NO_ERROR;
  126. }
  127.  
  128. /* prepare the knot information structures */
  129. static GLenum
  130. fill_knot_structures(GLUnurbsObj *nobj,knot_str_type *geom_knot,
  131.     knot_str_type *color_knot, knot_str_type *normal_knot,
  132.     knot_str_type *texture_knot)
  133. {
  134.     GLint order;
  135.     GLfloat *knot;
  136.     GLint nknots;
  137.     GLint t_min,t_max;
  138.  
  139.     geom_knot->unified_knot=NULL;
  140.     knot=geom_knot->knot=nobj->curve.geom.knot;
  141.     nknots=geom_knot->nknots=nobj->curve.geom.knot_count;
  142.     order=geom_knot->order=nobj->curve.geom.order;
  143.     geom_knot->delta_nknots=0;
  144.     t_min=geom_knot->t_min=order-1;
  145.     t_max=geom_knot->t_max=nknots-order;
  146.     if(fabs(knot[t_min]-knot[t_max])<EPSILON)
  147.     {
  148.         call_user_error(nobj,GLU_NURBS_ERROR3);
  149.         return GLU_ERROR;
  150.     }
  151.     if(fabs(knot[0]-knot[t_min])<EPSILON)
  152.     {
  153.         /* knot open at beggining */
  154.         geom_knot->open_at_begin=GL_TRUE;
  155.     }
  156.     else
  157.         geom_knot->open_at_begin=GL_FALSE;
  158.     if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
  159.     {
  160.         /* knot open at end */
  161.         geom_knot->open_at_end=GL_TRUE;
  162.     }
  163.     else
  164.         geom_knot->open_at_end=GL_FALSE;
  165.     if(nobj->curve.color.type!=GLU_INVALID_ENUM)
  166.     {
  167.         color_knot->unified_knot=(GLfloat *)1;
  168.         knot=color_knot->knot=nobj->curve.color.knot;
  169.         nknots=color_knot->nknots=nobj->curve.color.knot_count;
  170.         order=color_knot->order=nobj->curve.color.order;
  171.         color_knot->delta_nknots=0;
  172.         t_min=color_knot->t_min=order-1;
  173.         t_max=color_knot->t_max=nknots-order;
  174.         if(fabs(knot[t_min]-knot[t_max])<EPSILON)
  175.         {
  176.             call_user_error(nobj,GLU_NURBS_ERROR3);
  177.             return GLU_ERROR;
  178.         }
  179.         if(fabs(knot[0]-knot[t_min])<EPSILON)
  180.         {
  181.             /* knot open at beggining */
  182.             color_knot->open_at_begin=GL_TRUE;
  183.         }
  184.         else
  185.             color_knot->open_at_begin=GL_FALSE;
  186.         if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
  187.         {
  188.             /* knot open at end */
  189.             color_knot->open_at_end=GL_TRUE;
  190.         }
  191.         else
  192.             color_knot->open_at_end=GL_FALSE;
  193.     }
  194.     else
  195.         color_knot->unified_knot=NULL;
  196.     if(nobj->curve.normal.type!=GLU_INVALID_ENUM)
  197.     {
  198.         normal_knot->unified_knot=(GLfloat *)1;
  199.         knot=normal_knot->knot=nobj->curve.normal.knot;
  200.         nknots=normal_knot->nknots=nobj->curve.normal.knot_count;
  201.         order=normal_knot->order=nobj->curve.normal.order;
  202.         normal_knot->delta_nknots=0;
  203.         t_min=normal_knot->t_min=order-1;
  204.         t_max=normal_knot->t_max=nknots-order;
  205.         if(fabs(knot[t_min]-knot[t_max])<EPSILON)
  206.         {
  207.             call_user_error(nobj,GLU_NURBS_ERROR3);
  208.             return GLU_ERROR;
  209.         }
  210.         if(fabs(knot[0]-knot[t_min])<EPSILON)
  211.         {
  212.             /* knot open at beggining */
  213.             normal_knot->open_at_begin=GL_TRUE;
  214.         }
  215.         else
  216.             normal_knot->open_at_begin=GL_FALSE;
  217.         if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
  218.         {
  219.             /* knot open at end */
  220.             normal_knot->open_at_end=GL_TRUE;
  221.         }
  222.         else
  223.             normal_knot->open_at_end=GL_FALSE;
  224.     }
  225.     else
  226.         normal_knot->unified_knot=NULL;
  227.     if(nobj->curve.texture.type!=GLU_INVALID_ENUM)
  228.     {
  229.         texture_knot->unified_knot=(GLfloat *)1;
  230.         knot=texture_knot->knot=nobj->curve.texture.knot;
  231.         nknots=texture_knot->nknots=nobj->curve.texture.knot_count;
  232.         order=texture_knot->order=nobj->curve.texture.order;
  233.         texture_knot->delta_nknots=0;
  234.         t_min=texture_knot->t_min=order-1;
  235.         t_max=texture_knot->t_max=nknots-order;
  236.         if(fabs(knot[t_min]-knot[t_max])<EPSILON)
  237.         {
  238.             call_user_error(nobj,GLU_NURBS_ERROR3);
  239.             return GLU_ERROR;
  240.         }
  241.         if(fabs(knot[0]-knot[t_min])<EPSILON)
  242.         {
  243.             /* knot open at beggining */
  244.             texture_knot->open_at_begin=GL_TRUE;
  245.         }
  246.         else
  247.             texture_knot->open_at_begin=GL_FALSE;
  248.         if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
  249.         {
  250.             /* knot open at end */
  251.             texture_knot->open_at_end=GL_TRUE;
  252.         }
  253.         else
  254.             texture_knot->open_at_end=GL_FALSE;
  255.     }
  256.     else
  257.         texture_knot->unified_knot=NULL;
  258.     return GLU_NO_ERROR;
  259. }
  260.  
  261. /* covert the NURBS curve into a series of adjacent Bezier curves */
  262. static GLenum
  263. convert_curve(knot_str_type *the_knot, curve_attribs *attrib,
  264.     GLfloat **new_ctrl,GLint *ncontrol)
  265. {
  266.     GLenum err;
  267.  
  268.     if((err=explode_knot(the_knot))!=GLU_NO_ERROR)
  269.     {
  270.         if(the_knot->unified_knot)
  271.         {
  272.             free(the_knot->unified_knot);
  273.             the_knot->unified_knot=NULL;
  274.         }
  275.         return err;
  276.     }
  277.     if(the_knot->unified_knot)
  278.     {
  279.         free(the_knot->unified_knot);
  280.         the_knot->unified_knot=NULL;
  281.     }
  282.     if((err=calc_alphas(the_knot))!=GLU_NO_ERROR)
  283.     {
  284.         free(the_knot->new_knot);
  285.         return err;
  286.     }
  287.     free(the_knot->new_knot);
  288.     if((err=calc_new_ctrl_pts(attrib->ctrlarray,attrib->stride,the_knot,
  289.                             attrib->dim,new_ctrl,ncontrol))
  290.         !=GLU_NO_ERROR)
  291.     {
  292.         free(the_knot->alpha);
  293.         return err;
  294.     }
  295.     free(the_knot->alpha);
  296.     return GLU_NO_ERROR;
  297. }
  298.  
  299. /* covert curves - geometry and possible attribute ones into equivalent */
  300. /* sequence of adjacent Bezier curves */
  301. static GLenum
  302. convert_curves(GLUnurbsObj *nobj, GLfloat **new_geom_ctrl,
  303.     GLint *ncontrol, GLfloat **new_color_ctrl, GLfloat **new_normal_ctrl,
  304.     GLfloat **new_texture_ctrl)
  305. {
  306.     knot_str_type    geom_knot,color_knot,normal_knot,texture_knot;
  307.     GLint            junk;
  308.     GLenum            err;
  309.  
  310.     *new_color_ctrl=*new_normal_ctrl=*new_texture_ctrl=NULL;
  311.  
  312.     if(fill_knot_structures(nobj,&geom_knot,&color_knot,&normal_knot,
  313.             &texture_knot)!=GLU_NO_ERROR)
  314.         return GLU_ERROR;
  315.  
  316.     /* unify knots - all knots should have the same number of working */
  317.     /* ranges */
  318.     if((err=select_knot_working_range(nobj,&geom_knot,&color_knot,&normal_knot,
  319.                 &texture_knot))!=GLU_NO_ERROR)
  320.     {
  321.         return err;
  322.     }
  323.     /* convert the geometry curve */
  324.     nobj->curve.geom.dim=get_curve_dim(nobj->curve.geom.type);
  325.     if((err=convert_curve(&geom_knot,&(nobj->curve.geom),new_geom_ctrl,
  326.                         ncontrol))!=GLU_NO_ERROR)
  327.     {
  328.         free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot);
  329.         call_user_error(nobj,err);
  330.         return err;
  331.     }
  332.     /* if additional attributive curves are given convert them as well */
  333.     if(color_knot.unified_knot)
  334.     {
  335.         nobj->curve.color.dim=get_curve_dim(nobj->curve.color.type);
  336.         if((err=convert_curve(&color_knot,&(nobj->curve.color),
  337.             new_color_ctrl,&junk))!=GLU_NO_ERROR)
  338.         {
  339.             free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot);
  340.             free(*new_geom_ctrl);
  341.             call_user_error(nobj,err);
  342.             return err;
  343.         }
  344.     }
  345.     if(normal_knot.unified_knot)
  346.     {
  347.         nobj->curve.normal.dim=get_curve_dim(nobj->curve.normal.type);
  348.         if((err=convert_curve(&normal_knot,&(nobj->curve.normal),
  349.             new_normal_ctrl,&junk))!=GLU_NO_ERROR)
  350.         {
  351.             free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot);
  352.             free(*new_geom_ctrl);
  353.             if(*new_color_ctrl)
  354.                 free(*new_color_ctrl);
  355.             call_user_error(nobj,err);
  356.             return err;
  357.         }
  358.     }
  359.     if(texture_knot.unified_knot)
  360.     {
  361.         nobj->curve.texture.dim=get_curve_dim(nobj->curve.texture.type);
  362.         if((err=convert_curve(&texture_knot,&(nobj->curve.texture),
  363.             new_texture_ctrl,&junk))!=GLU_NO_ERROR)
  364.         {
  365.             free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot);
  366.             free(*new_geom_ctrl);
  367.             if(*new_color_ctrl)
  368.                 free(*new_color_ctrl);
  369.             if(*new_normal_ctrl)
  370.                 free(*new_normal_ctrl);
  371.             call_user_error(nobj,err);
  372.             return err;
  373.         }
  374.     }
  375.     return GLU_NO_ERROR;
  376. }
  377.  
  378. /* main NURBS curve procedure */
  379. void do_nurbs_curve( GLUnurbsObj *nobj)
  380. {
  381.     GLint geom_order,color_order=0,normal_order=0,texture_order=0;
  382.     GLenum geom_type;
  383.     GLint n_ctrl;
  384.     GLfloat *new_geom_ctrl,*new_color_ctrl,*new_normal_ctrl,*new_texture_ctrl;
  385.     GLfloat *geom_ctrl,*color_ctrl,*normal_ctrl,*texture_ctrl;
  386.     GLint *factors;
  387.     GLint i,j;
  388.     GLint geom_dim,color_dim=0,normal_dim=0,texture_dim=0;
  389.  
  390.     /* test the user supplied data */
  391.     if(test_nurbs_curves(nobj)!=GLU_NO_ERROR)
  392.         return;
  393.  
  394.     if(convert_curves(nobj,&new_geom_ctrl,&n_ctrl,&new_color_ctrl,
  395.                     &new_normal_ctrl,&new_texture_ctrl)!=GLU_NO_ERROR)
  396.         return;
  397.  
  398.     geom_order=nobj->curve.geom.order;
  399.     geom_type=nobj->curve.geom.type;
  400.     geom_dim=nobj->curve.geom.dim;
  401.  
  402.     if(glu_do_sampling_2D(nobj,new_geom_ctrl,n_ctrl,geom_order,geom_dim,
  403.                         &factors)
  404.         !=GLU_NO_ERROR)
  405.     {
  406.         free(new_geom_ctrl);
  407.         if(new_color_ctrl)
  408.             free(new_color_ctrl);
  409.         if(new_normal_ctrl)
  410.             free(new_normal_ctrl);
  411.         if(new_texture_ctrl)
  412.             free(new_texture_ctrl);
  413.         return;
  414.     }
  415.     glEnable(geom_type);
  416.     if(new_color_ctrl)
  417.     {
  418.         glEnable(nobj->curve.color.type);
  419.         color_dim=nobj->curve.color.dim;
  420.         color_ctrl=new_color_ctrl;
  421.         color_order=nobj->curve.color.order;
  422.     }
  423.     if(new_normal_ctrl)
  424.     {
  425.         glEnable(nobj->curve.normal.type);
  426.         normal_dim=nobj->curve.normal.dim;
  427.         normal_ctrl=new_normal_ctrl;
  428.         normal_order=nobj->curve.normal.order;
  429.     }
  430.     if(new_texture_ctrl)
  431.     {
  432.         glEnable(nobj->curve.texture.type);
  433.         texture_dim=nobj->curve.texture.dim;
  434.         texture_ctrl=new_texture_ctrl;
  435.         texture_order=nobj->curve.texture.order;
  436.     }
  437.     for(i=0 , j=0, geom_ctrl=new_geom_ctrl;
  438.         i<n_ctrl;
  439.         i+=geom_order , j++ , geom_ctrl+=geom_order*geom_dim)
  440.     {
  441.         if(fine_culling_test_2D(nobj,geom_ctrl,geom_order,geom_dim,geom_dim))
  442.         {
  443.             color_ctrl+=color_order*color_dim;
  444.             normal_ctrl+=normal_order*normal_dim;
  445.             texture_ctrl+=texture_order*texture_dim;
  446.             continue;
  447.         }
  448.         glMap1f(geom_type, 0.0, 1.0, geom_dim, geom_order, geom_ctrl);
  449.         if(new_color_ctrl)
  450.         {
  451.             glMap1f(nobj->curve.color.type, 0.0, 1.0, color_dim,
  452.                 color_order,color_ctrl);
  453.             color_ctrl+=color_order*color_dim;
  454.         }
  455.         if(new_normal_ctrl)
  456.         {
  457.             glMap1f(nobj->curve.normal.type, 0.0, 1.0, normal_dim,
  458.                 normal_order,normal_ctrl);
  459.             normal_ctrl+=normal_order*normal_dim;
  460.         }
  461.         if(new_texture_ctrl)
  462.         {
  463.             glMap1f(nobj->curve.texture.type, 0.0, 1.0, texture_dim,
  464.                 texture_order,texture_ctrl);
  465.             texture_ctrl+=texture_order*texture_dim;
  466.         }
  467.         glMapGrid1f(factors[j],0.0,1.0);
  468.         glEvalMesh1(GL_LINE,0,factors[j]);
  469.     }
  470.     free(new_geom_ctrl);
  471.     free(factors);
  472.     if(new_color_ctrl)
  473.         free(new_color_ctrl);
  474.     if(new_normal_ctrl)
  475.         free(new_normal_ctrl);
  476.     if(new_texture_ctrl)
  477.         free(new_texture_ctrl);
  478. }
  479.  
  480.  
  481.